﻿
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;

using DotSpatial.Topology;

using DotSpatial.Symbology;

using Point = System.Drawing.Point;


namespace HaGisPack
{
    class FourSideMF : FMapFunctionBase
    {


        #region private variables

      
        private List<Coordinate> _coordinates;
      
        private System.Drawing.Point _mousePosition;
        public bool _standBy;
        private IMapLineLayer _tempLayer;
      
      
        private List<List<Coordinate>> _parts;
 

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of AddShapeFunction
        /// </summary>
        public FourSideMF()
        {
            Configure();

        }
        /// <summary>
        /// Creates a new instance of AddShapeFunction, but specifies
        /// the Map that this function should be applied to.
        /// </summary>
        /// <param name="map"></param>
        public FourSideMF(IMap map)
            : base(map)
        {
            Configure();
        }

        private void Configure()
        {
          
            _parts = new List<List<Coordinate>>();
        }


        #endregion


        #region Methods

        protected override void OnActivate()
        {
            
           
            if (_standBy == false) _coordinates = new List<Coordinate>();
            if (_tempLayer != null)
            {
                Map.MapFrame.DrawingLayers.Remove(_tempLayer);
                Map.MapFrame.Invalidate();
                Map.Invalidate();
                _tempLayer = null;
            }
            _standBy = false;
            base.OnActivate();
        }

        /// <summary>
        /// Allows for new behavior during deactivation.
        /// </summary>
        protected override void OnDeactivate()
        {
            if (_standBy) return;
            // Don't completely deactivate, but rather go into standby mode
            // where we draw only the content that we have actually locked in.
            _standBy = true;
            // base.OnDeactivate();
            //if (_coordinateDialog != null) _coordinateDialog.Hide();
            if (_coordinates != null && _coordinates.Count > 1)
            {
                LineString ls = new LineString(_coordinates);
                FeatureSet fs = new FeatureSet(FeatureType.Line);
                fs.Features.Add(new Feature(ls));
                MapLineLayer gll = new MapLineLayer(fs);
                //gll.Symbolizer.FillColor = Color.Blue;
                gll.Symbolizer.ScaleMode = ScaleMode.Symbolic;
                gll.Symbolizer.Smoothing = true;
                gll.MapFrame = Map.MapFrame;

                _tempLayer = gll;
                Map.MapFrame.DrawingLayers.Add(gll);
                // Map.MapFrame.Initialize(_tempLayer);
                Map.MapFrame.Invalidate();
                Map.Invalidate();
            }

        }

        protected override void OnDraw(MapDrawArgs e)
        {
            if (_standBy) return;
           

            // Draw any completed parts first so that they are behind my active drawing content.
            if (_parts != null)
            {
                GraphicsPath gp = new GraphicsPath();

                List<Point> partPoints = new List<Point>();
                foreach (List<Coordinate> part in _parts)
                {

                    gp.AddPolygon(partPoints.ToArray());

                    partPoints.Clear();
                }
                e.Graphics.DrawPath(Pens.Blue, gp);

                Brush fill = new SolidBrush(Color.FromArgb(70, Color.LightCyan));
                e.Graphics.FillPath(fill, gp);
                fill.Dispose();

            }

            Pen bluePen = new Pen(Color.Blue, 2F);
            Pen redPen = new Pen(Color.Red, 3F);
            Brush redBrush = new SolidBrush(Color.Red);
            List<Point> points = new List<Point>();
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (_coordinates != null)
            {
                foreach (Coordinate coord in _coordinates)
                {
                    points.Add(Map.ProjToPixel(coord));
                }
                foreach (Point pt in points)
                {
                    e.Graphics.FillRectangle(redBrush, new Rectangle(pt.X - 2, pt.Y - 2, 4, 4));
                }

                if (points.Count > 1)
                {

                    e.Graphics.DrawLines(bluePen, points.ToArray());
                }

                if (points.Count > 0 && _standBy == false)
                {

                    e.Graphics.DrawLine(redPen, points[points.Count - 1], _mousePosition);
                   
                }
            }


            bluePen.Dispose();
            redPen.Dispose();
            redBrush.Dispose();
            base.OnDraw(e);
        }

        /// <summary>
        /// updates the auto-filling X and Y coordinates
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(GeoMouseArgs e)
        {

            if (_standBy) return;
            //_coordinateDialog.X = e.GeographicLocation.X;
            //_coordinateDialog.Y = e.GeographicLocation.Y;
            if (_coordinates != null && _coordinates.Count > 0)
            {
                List<System.Drawing.Point> points = new List<System.Drawing.Point>();
                foreach (Coordinate coord in _coordinates)
                {
                    points.Add(Map.ProjToPixel(coord));
                }
                Rectangle oldRect = Global.GetRectangle(_mousePosition, points[points.Count - 1]);
                Rectangle newRect = Global.GetRectangle(e.Location, points[points.Count - 1]);
                Rectangle invalid = Rectangle.Union(newRect, oldRect);
                invalid.Inflate(20, 20);
                Map.Invalidate(invalid);
            }
            _mousePosition = e.Location;
            base.OnMouseMove(e);
        }
                
        int PolyID = 1;


        /// <summary>
        /// Handles the Mouse-Up situation
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(GeoMouseArgs e)
        {
            if (_standBy) return;

            if (_coordinates == null) _coordinates = new List<Coordinate>();
            _coordinates.Add(e.GeographicLocation);

           
            if (_coordinates.Count > 1)
            {
                System.Drawing.Point p1 = Map.ProjToPixel(_coordinates[_coordinates.Count - 1]);
                System.Drawing.Point p2 = Map.ProjToPixel(_coordinates[_coordinates.Count - 2]);
                Rectangle invalid = Global.GetRectangle(p1, p2);
                invalid.Inflate(20, 20);
                Map.Invalidate(invalid);
            }

            if (_coordinates.Count == 4)
            {
                this.FinishShape();
            }



            base.OnMouseUp(e);
        }

     

        /// <summary>
        /// Finish shape
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void FinishShape()
        {

            foreach (IFeature f in (this.Parent.Parent.LayerSys.CurrentLayer.DataSet as IFeatureSet).Features)
            {
                PolyID = 1;
                if (PolyID <= int.Parse(f.DataRow["id"].ToString().Substring(1)))
                {
                    PolyID = int.Parse(f.DataRow["id"].ToString().Substring(1)) + 1;
                }
            }

            string id = "A" + PolyID.ToString();
            FPolyShape ps = new FPolyShape(id, _coordinates.ToArray());
            this.OnShapeAdded(ps);
            //PolyID++;


            _coordinates = new List<Coordinate>();
            _parts = new List<List<Coordinate>>();

        }

        /// <summary>
        /// Finish part
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void FinishPart(object sender, EventArgs e)
        {
            _parts.Add(_coordinates);
            _coordinates = new List<Coordinate>();
            Map.Invalidate();
        }

        /// <summary>
        /// Occurs when this function is removed.
        /// </summary>
        protected override void OnUnload()
        {
            if (Enabled)
            {
                _coordinates = null;
                //_coordinateDialog.Hide();
            }
            if (_tempLayer != null)
            {
                Map.MapFrame.DrawingLayers.Remove(_tempLayer);
                Map.MapFrame.Invalidate();

                _tempLayer = null;
            }
            Map.Invalidate();
        }



        protected override void OnMouseWheel(GeoMouseArgs e)
        {
            base.OnMouseWheel(e);

            Rectangle r = e.Map.MapFrame.View;
            int w = r.Width;
            int h = r.Height;

            int scale = 5;

            if (e.Delta < 0)
            {
                r.Inflate(r.Width / (2 * scale), r.Height / (scale * 2));
                r.X += w / (2 * scale) - e.X / (scale);
                r.Y += h / (2 * scale) - e.Y / (scale);
                e.Map.MapFrame.View = r;
                e.Map.MapFrame.ResetExtents();
            }
            else
            {
                r.Inflate(-r.Width / (4 * scale), -r.Height / (4 * scale));
                // The mouse cursor should anchor the geographic location during zoom.
                r.X += (e.X / (2 * scale)) - w / (4 * scale);
                r.Y += (e.Y / (2 * scale)) - h / (4 * scale);
                e.Map.MapFrame.View = r;
                e.Map.MapFrame.ResetExtents();
            }

        }


        #endregion

       
              
    }
}



